﻿using Caliburn.Micro;
using Microsoft.Win32;
using SD.Common;
using SD.Infrastructure.DTOBase;
using SD.Infrastructure.WPF.Caliburn.Aspects;
using SD.Infrastructure.WPF.Caliburn.Base;
using SD.Infrastructure.WPF.Extensions;
using SD.Infrastructure.WPF.Interfaces;
using SD.Infrastructure.WPF.Models;
using SD.IOC.Core.Mediators;
using SD.Toolkits.Excel;
using SlamDunk.MES.Client.ViewModels.Facility;
using SlamDunk.MES.IAppService.DTOs.Outputs.ResourceContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.MES.Presentation;
using SlamDunk.MES.Presentation.Maps;
using SlamDunk.MES.Presentation.Models.ExportModels;
using SlamDunk.MES.Presentation.Models.NotifyModels;
using SlamDunk.MES.ReportView.Models;
using SlamDunk.ValueObjects.Enums;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel.Extensions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace SlamDunk.MES.Client.ViewModels.StockQuery
{
    /// <summary>
    /// 库存首页ViewModel
    /// </summary>
    public class IndexViewModel : ScreenBase, IPaginatable
    {
        #region # 字段及构造器

        /// <summary>
        /// 库存单据服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IStockOrderContract> _iStockOrderContract;

        /// <summary>
        /// 资源定义服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IResourceContract> _iResourceContract;

        /// <summary>
        /// 基础定义服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IFoundationContract> _iFoundationContract;

        /// <summary>
        /// 库存管理服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IStockManageContract> _iStockManageContract;

        /// <summary>
        /// 窗口管理器
        /// </summary>
        private readonly IWindowManager _windowManager;

        /// <summary>
        /// 依赖注入构造器
        /// </summary>
        public IndexViewModel(ServiceProxy<IStockOrderContract> iStockOrderContract, ServiceProxy<IResourceContract> iResourceContract, ServiceProxy<IFoundationContract> iFoundationContract, ServiceProxy<IStockManageContract> iStockManageContract, IWindowManager windowManager)
        {
            this._iStockOrderContract = iStockOrderContract;
            this._iResourceContract = iResourceContract;
            this._iFoundationContract = iFoundationContract;
            this._iStockManageContract = iStockManageContract;
            this._windowManager = windowManager;
            //默认值
            this.PageIndex = 1;
            this.PageSize = 20;
        }
        #endregion

        #region # 属性

        #region 页码 —— int PageIndex
        /// <summary>
        /// 页码
        /// </summary>
        [DependencyProperty]
        public int PageIndex { get; set; }
        #endregion

        #region 页容量 —— int PageSize
        /// <summary>
        /// 页容量
        /// </summary>
        [DependencyProperty]
        public int PageSize { get; set; }
        #endregion

        #region 总记录数 —— int RowCount
        /// <summary>
        /// 总记录数
        /// </summary>
        [DependencyProperty]
        public int RowCount { get; set; }
        #endregion

        #region 总页数 —— int PageCount
        /// <summary>
        /// 总页数
        /// </summary>
        [DependencyProperty]
        public int PageCount { get; set; }
        #endregion

        #region 关键字
        /// <summary>
        /// 关键字
        /// </summary>
        [DependencyProperty]
        public string Keywords { get; set; }
        #endregion

        #region 储存类型列表
        /// <summary>
        /// 储存类型列表
        /// </summary>
        [DependencyProperty]
        public IDictionary<string, string> StorageLocationTypes { get; set; }
        #endregion

        #region 储存位置列表
        /// <summary>
        /// 储存位置列表
        /// </summary>
        [DependencyProperty]
        public ObservableCollection<IdentiferNameNm> StorageLocations { get; set; }
        #endregion

        #region 供应商列表
        /// <summary>
        /// 供应商列表
        /// </summary>
        [DependencyProperty]
        public ObservableCollection<IdentiferNameNm> Suppliers { get; set; }
        #endregion

        #region 已选库存类型
        /// <summary>
        /// 已选库存类型
        /// </summary>
        [DependencyProperty]
        public StorageLocationType? SelectedStorageLocationType { get; set; }
        #endregion

        #region 已选储存位置
        /// <summary>
        /// 已选储存位置
        /// </summary>
        [DependencyProperty]
        public IdentiferNameNm SelectedStorageLocation { get; set; }
        #endregion

        #region 已选供应商
        /// <summary>
        /// 已选供应商
        /// </summary>
        [DependencyProperty]
        public IdentiferNameNm SelectedSupplier { get; set; }
        #endregion

        #region 物料库存列表
        /// <summary>
        /// 物料库存列表
        /// </summary>
        [DependencyProperty]
        public ObservableCollection<Wrap<MaterialStockInfo>> MaterialStocks { get; set; }
        #endregion

        #region 储存位置列表显示隐藏
        /// <summary>
        /// 储存位置列表显示隐藏
        /// </summary>
        [DependencyProperty]
        public Visibility SourceStorageLocationComboBoxVisibility { get; set; }
        #endregion

        #region 储存位置描述显示隐藏
        /// <summary>
        /// 储存位置描述显示隐藏
        /// </summary>
        [DependencyProperty]
        public Visibility SourceStorageLocationTextVisibility { get; set; }
        #endregion

        #region 存位置描述
        /// <summary>
        /// 存位置描述
        /// </summary>
        [DependencyProperty]
        public string SourceStorageLocationnText { get; set; }
        #endregion

        #region 工厂模型名称
        /// <summary>
        /// 工厂模型名称
        /// </summary>
        [DependencyProperty]
        public string FacilityName { get; set; }
        #endregion

        #region 工厂模型Id
        /// <summary>
        /// 工厂模型Id
        /// </summary>
        [DependencyProperty]
        public Guid? FacilityId { get; set; }
        #endregion
        #endregion

        #region # 方法

        //Initializations

        #region 初始化 —— override async Task OnInitializeAsync(CancellationToken cancellationToken)
        /// <summary>
        /// 初始化
        /// </summary>
        protected override async Task OnInitializeAsync(CancellationToken cancellationToken)
        {
            this.StorageLocationTypes = typeof(StorageLocationType).GetEnumMembers();
            PageModel<EnterpriseInfo> Enterprises = await Task.Run(() =>
                      this._iResourceContract.Channel.GetEnterprisesByPage(
                         null,//关键字
                         EnterpriseType.Supplier,//工厂模型Id
                         null,
                         1,
                         int.MaxValue)//上级节点Id
                   );
            var EnterpriseModels = Enterprises.Datas.Select(x => x.ToIdentiferName());
            this.Suppliers = new ObservableCollection<IdentiferNameNm>(EnterpriseModels);
            this.SourceStorageLocationComboBoxVisibility = Visibility.Visible;
            this.SourceStorageLocationTextVisibility = Visibility.Collapsed;
            await this.ReloadMaterialStock();
        }
        #endregion


        //Actions

        #region 单据导出 —— async void ExportStockManage()
        /// <summary>
        /// 单据导出
        /// </summary>
        public async void ExportStockManage()
        {
            PageModel<MaterialStockInfo> pageModel = await Task.Run(() => this._iStockManageContract.Channel.GetMaterialStocksByPage(
                this.Keywords,//关键字
                null,//物料定义Id
                null,//物料批次Id
                this.SelectedSupplier?.Id,//供应商Id
                this.SelectedStorageLocationType,//储存位置类型
                this.SelectedStorageLocationType == StorageLocationType.Description ? this.SourceStorageLocationnText : this.SelectedStorageLocation?.Id.ToString(),//储存位置Id
                this.FacilityId,//工厂模型Id
                this.PageIndex,//页码
               this.PageSize));
            MaterialStockEm[] materialStockEms = pageModel.Datas.Select(x => x.ToExportView()).ToArray();
            if (!materialStockEms.Any())
            {
                MessageBox.Show("导出数据为空，不能进行导出！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            SaveFileDialog saveDg = new SaveFileDialog
            {
                Filter = Constants.ExeclFileExtensionsFilter,
                FileName = $"库存盘点表_{DateTime.Now.ToString(Constants.ExportFileTimeFormat)}",
                AddExtension = true,
                RestoreDirectory = true
            };
            if (saveDg.ShowDialog() == true)
            {
                string filePath = saveDg.FileName;
                ExcelWriter.WriteFile(materialStockEms, filePath);
            }
        }
        #endregion

        #region 搜索
        /// <summary>
        /// 搜索
        /// </summary>
        public async void LoadStockManage()
        {
            await this.ReloadMaterialStock();
        }
        #endregion

        #region 加载源储存位置
        /// <summary>
        /// 加载源储存位置
        /// </summary>
        public async void LoadSourceStorageLocationType()
        {
            this.Busy();

            await this.ReloadSourceStorageLocation();

            this.Idle();
        }
        #endregion

        #region 清空工厂模型 —— async void ClearFacility()
        /// <summary>
        /// 清空工厂模型
        /// </summary>
        public async void ClearFacility()
        {
            this.FacilityId = null;
            this.FacilityName = string.Empty;
        }
        #endregion

        #region 加载工厂模型-弹出层
        /// <summary>
        /// 加载工厂模型-弹出层
        /// </summary>
        public async void SelectFacility()
        {
            this.Busy();
            SelectFacilityViewModel viewModel = ResolveMediator.Resolve<SelectFacilityViewModel>();
            bool? result = await this._windowManager.ShowDialogAsync(viewModel);
            if (result == true)
            {
                this.FacilityId = viewModel.SelectedFacility.Id;
                this.FacilityName = viewModel.SelectedFacility.Name;
            }
            this.Idle();
        }
        #endregion


        //private

        #region 加载取物料库存列表 —— async Task ReloadMaterialStock()
        /// <summary>
        /// 加载取物料库存列表
        /// </summary>
        private async Task ReloadMaterialStock()
        {
            this.Busy();

            PageModel<MaterialStockInfo> pageModel = await Task.Run(() =>
                this._iStockManageContract.Channel.GetMaterialStocksByPage(
                    this.Keywords, //关键字
                    null, //物料定义Id
                    null, //物料批次Id
                    this.SelectedSupplier?.Id, //供应商Id
                    this.SelectedStorageLocationType, //储存位置类型
                    this.SelectedStorageLocationType == StorageLocationType.Description
                        ? this.SourceStorageLocationnText
                        : this.SelectedStorageLocation?.Id.ToString(), //储存位置Id
                    this.FacilityId, //工厂模型Id
                    this.PageIndex, //页码
                    this.PageSize));
            this.RowCount = pageModel.RowCount;
            this.PageCount = pageModel.PageCount;
            this.MaterialStocks = new ObservableCollection<Wrap<MaterialStockInfo>>(pageModel.Datas.Select(x => x.Wrap()));

            this.Idle();
        }
        #endregion

        #region 加载源储存位置列表 —— async Task ReloadSourceStorageLocation()
        /// <summary>
        /// 加载源储存位置列表
        /// </summary>
        private async Task ReloadSourceStorageLocation()
        {
            #region # 验证

            if (this.SelectedStorageLocationType == null)
            {
                this.StorageLocations = new ObservableCollection<IdentiferNameNm>();
                return;
            }
            #endregion

            //显示隐藏库位列表
            this.SourceStorageLocationComboBoxVisibility = Visibility.Visible;
            this.SourceStorageLocationTextVisibility = Visibility.Collapsed;
            switch (this.SelectedStorageLocationType)
            {
                case StorageLocationType.ProductionDomain://生产域
                    IEnumerable<IAppService.DTOs.Outputs.FoundationContext.FacilityInfo> Facilities = await Task.Run(() =>
                    this._iFoundationContract.Channel.GetFacilities(
                        null,//关键字
                        null,//工厂模型层次
                        FacilityType.ProductionDomain,//工厂模型类型
                        null)//上级节点Id
                    );
                    IEnumerable<IdentiferNameNm> Facilitiemodels = Facilities.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(Facilitiemodels);
                    break;
                case StorageLocationType.BusinessDomain://业务域
                    Facilities = await Task.Run(() =>
                    this._iFoundationContract.Channel.GetFacilities(
                        null,//关键字
                        null,//工厂模型层次
                        FacilityType.BusinessDomain,//工厂模型类型
                        null)//上级节点Id
                    );
                    Facilitiemodels = Facilities.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(Facilitiemodels);
                    break;
                case StorageLocationType.StorageDomain://储存域
                    Facilities = await Task.Run(() =>
                   this._iFoundationContract.Channel.GetFacilities(
                      null,//关键字
                      null,//工厂模型层次
                      FacilityType.StorageDomain,//工厂模型类型
                      null)//上级节点Id
                  );
                    Facilitiemodels = Facilities.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(Facilitiemodels);
                    break;
                case StorageLocationType.Person://人员
                    PageModel<PersonInfo> Persons = await Task.Run(() =>
                      this._iResourceContract.Channel.GetPersonsByPage(
                         null,//关键字
                         null,//工厂模型Id
                         null,//人员类Id
                         1,
                         int.MaxValue)//上级节点Id
                   );
                    IEnumerable<IdentiferNameNm> Personsmodels = Persons.Datas.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(Personsmodels);
                    break;
                case StorageLocationType.Team://班组
                    PageModel<TeamInfo> Teams = await Task.Run(() =>
                     this._iResourceContract.Channel.GetTeamsByPage(
                        null,//关键字
                        null,//工厂模型Id
                        1,
                        int.MaxValue)//上级节点Id
                  );
                    IEnumerable<IdentiferNameNm> TeamModels = Teams.Datas.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(TeamModels);
                    break;
                case StorageLocationType.Customer://客户
                    PageModel<EnterpriseInfo> Enterprises = await Task.Run(() =>
                    this._iResourceContract.Channel.GetEnterprisesByPage(
                       null,//关键字
                       EnterpriseType.Customer,//工厂模型Id
                       null,
                       1,
                       int.MaxValue)//上级节点Id
                 );
                    IEnumerable<IdentiferNameNm> EnterpriseModels = Enterprises.Datas.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(EnterpriseModels);
                    break;
                case StorageLocationType.Supplier://供应商
                    Enterprises = await Task.Run(() =>
                   this._iResourceContract.Channel.GetEnterprisesByPage(
                      null,//关键字
                      EnterpriseType.Supplier,//工厂模型Id
                      null,
                      1,
                      int.MaxValue)//上级节点Id
                );
                    EnterpriseModels = Enterprises.Datas.Select(x => x.ToIdentiferName());
                    this.StorageLocations = new ObservableCollection<IdentiferNameNm>(EnterpriseModels);
                    break;
                case StorageLocationType.Description://描述
                    this.SourceStorageLocationComboBoxVisibility = Visibility.Collapsed;
                    this.SourceStorageLocationTextVisibility = Visibility.Visible;
                    break;
            }
        }
        #endregion

        #endregion
    }
}
